/*--------------------------------------------------------------
 * File: m5stack_ota.c 编码类型：C语言  UTF-8
 * Author WRS (1352509846@qq.com)
 * 功能: M5STACK ota升级程序
 * Version 0.1
 * Date 2025-04-09
 *
 * @copyright Copyright (c) 2025
 *
----------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "m5stack_ota.h"
#include "sta.h"
#include "cJSON.h"
#include "esp_https_ota.h"
#include "esp_ota_ops.h"
#include "esp_crt_bundle.h"
#include "string.h"
#include "ui.h"

static const char *TAG = "OTA";

#include "cJSON.h"

/*--------------------------------------------------------------
 * 功能: 分段解析版本号，将字符串分段解析成三段数字
 * 
 * 参数: ver_str 
 * 返回值: Version 
----------------------------------------------------------------*/
static Version parse_version(const char *ver_str)
{
    Version ver = {0, 0, 0};
    // 跳过开头的 'V' 或 'v'
    if (ver_str[0] == 'V' || ver_str[0] == 'v')
    {
        ver_str++;
    }
    // 使用 sscanf 解析三段数字
    if (sscanf(ver_str, "%d.%d.%d", &ver.major, &ver.minor, &ver.patch) != 3)
    {
        ESP_LOGE(TAG, "Failed to parse version: %s", ver_str);
        return (Version){-1, -1, -1}; // 返回无效版本
    }
    return ver;
}

/*--------------------------------------------------------------
 * 功能: 比较版本号
 * 
 * 参数: new_ver 
 * 参数: min_ver 
 * 返回值: int 1: new_ver > min_ver 0: new_ver <= min_ver
----------------------------------------------------------------*/
static int is_version_greater(const char *new_ver, const char *min_ver)
{
    Version v_new = parse_version(new_ver);
    Version v_min = parse_version(min_ver);

    // 比较主版本号
    if (v_new.major > v_min.major)
        return 1;
    if (v_new.major < v_min.major)
        return 0;

    // 主版本相同，比较次版本号
    if (v_new.minor > v_min.minor)
        return 1;
    if (v_new.minor < v_min.minor)
        return 0;

    // 主次版本相同，比较修订号
    if (v_new.patch > v_min.patch)
        return 1;

    return 0; // 版本号 <= 最小版本
}

static void handle_ota_command(const char *json_str)
{
    cJSON *root = cJSON_Parse(json_str);
    if (!root)
    {
        ESP_LOGE(TAG, "JSON parse error: %s", json_str);
        return;
    }

    cJSON *ota = cJSON_GetObjectItem(root, "ota");
    if (ota)
    {
        cJSON *url = cJSON_GetObjectItem(ota, "url");
        cJSON *version = cJSON_GetObjectItem(ota, "version");
        if (url && version)
        {
            ESP_LOGI(TAG, "OTA指令: URL=%s, Version=%s", url->valuestring, version->valuestring);
            // 比较版本号
            if (is_version_greater(version->valuestring, Ver_str) != 1)
            {
                ESP_LOGI(TAG, "New version is Err, skip update");
                return;
            }
            esp_http_client_config_t config = {
                .url = url->valuestring,
                .crt_bundle_attach = esp_crt_bundle_attach,
                // .event_handler = _http_event_handler,
                .keep_alive_enable = true,
            };
            esp_https_ota_config_t ota_config = {
                .http_config = &config,
            };
            ESP_LOGI(TAG, "Attempting to download update from %s", config.url);
            Scr_OTA_init(); // 切换到升级界面

            esp_err_t ret = esp_https_ota(&ota_config);
            if (ret == ESP_OK)
            {
                ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
                // 打印下一次启动的分区（非当前运行分区）
                const esp_partition_t *target = esp_ota_get_next_update_partition(NULL);
                ESP_LOGI("OTA", "升级成功，下次启动分区: %s", target->label);
                esp_restart();
            }
            else
            {
                ESP_LOGE(TAG, "Firmware upgrade failed");
            }
        }
    }
    cJSON_Delete(root);
}
void handle_info_command(const char *json_str)
{
}

void data_process_task(void *pvParameters)
{
    mqtt_queue_msg_t *p_msg;
    while (1)
    {
        // 阻塞等待队列消息
        if (xQueueReceive(mqtt_queue, &p_msg, portMAX_DELAY) == pdTRUE)
        {
            // ESP_LOGI(TAG, "Topic=%s, Data=%s", p_msg->topic, p_msg->data);

            // 根据主题分类处理
            if (strcmp(p_msg->topic, MQTT_SUB_OTA_TOPIC) == 0)
            {
                handle_ota_command(p_msg->data); // 处理OTA指令
            }
            else if (strcmp(p_msg->topic, MQTT_SUB_INFO_TOPIC) == 0)
            {
                handle_info_command(p_msg->data); // 处理信息指令
            }
        }
    }
}

// 在app_main中启动任务
void ota_task_init()
{
    xTaskCreate(data_process_task, "data_process", 4096, NULL, 5, NULL);
}
